package app.service;

import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import refactor.entity.ApplyRecord;
import refactor.entity.Device;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import app.entity.Pager;
import app.utils.TimeUtils;
import refactor.mapper.DeviceMapper;
import siotwx.dao.ApplyrecordDao;
import siotwx.dao.CountsamefacaddressDao;
import siotwx.dao.DevbugDao;
import siotwx.dao.DeviceDao;
import siotwx.dao.DeviceinfoDao;
import siotwx.dao.DevicenumDao;
import siotwx.dao.DevlogsDao;
import siotwx.dao.EventlogDao;
import siotwx.dao.FacilitiesDao;
import siotwx.dao.FaultinfoDao;
import siotwx.dao.FaultnumDao;
import siotwx.dao.ModuleDao;
import siotwx.dao.OperatorviewDao;
import siotwx.entity.Countsamefacaddress;
import siotwx.entity.Devbug;
import siotwx.entity.Deviceinfo;
import siotwx.entity.Devicenum;
import siotwx.entity.Devlogs;
import siotwx.entity.Eventlog;
import siotwx.entity.Facilities;
import siotwx.entity.Faultinfo;
import siotwx.entity.Module;
import siotwx.entity.Operatorview;

/**
 * 这个类用于管理设备的业务逻辑
 * @author 昊琦
 *创建时间：2018年3月9日14:29:45
 */
@Service("DeviceManageService")
public class DeviceManageService {

	@Autowired
	@Qualifier("EventlogDao")
	private EventlogDao eventlogDao;
	
	@Autowired
	@Qualifier("FaultinfoDao")
	private FaultinfoDao faultinfoDao;
	
	@Autowired
	@Qualifier("DevicenumDao")
	private DevicenumDao devnumDao;
	
	@Autowired
	@Qualifier("DevbugDao")
	private DevbugDao devBugDao;
	
	@Autowired
	@Qualifier("DevlogsDao")
	private DevlogsDao devLogsDao;
	
	@Autowired
	@Qualifier("OperatorviewDao")
	private OperatorviewDao operatorviewDao;
	
	@Autowired
	@Qualifier("DeviceDao")
	private DeviceDao deviceDao;
	
	@Autowired
	@Qualifier("FaultnumDao")
	private FaultnumDao faultnumDao;
	
	@Autowired
	@Qualifier("ModuleDao")
	private ModuleDao moduleDao;
	
	@Autowired
	@Qualifier("CountsamefacaddressDao")
	private CountsamefacaddressDao csfaDao;
	
	@Autowired
	@Qualifier("FacilitiesDao")
	private FacilitiesDao faclitiesDao;
	
	@Autowired
	@Qualifier("DeviceinfoDao")
	private DeviceinfoDao devinfoDao;
	
	@Autowired
	@Qualifier("ApplyrecordDao")
	private ApplyrecordDao applyrecordDao;

	private DeviceMapper deviceMapper;

	@Autowired
	public void setDeviceMapper(DeviceMapper deviceMapper) {
		this.deviceMapper = deviceMapper;
	}

	public Device getDeviceByInternetDevId(String internetDevId){
		return deviceMapper.selectOne(new QueryWrapper<Device>().lambda().eq(Device::getInternetDeviceId,internetDevId));
	}

	public Facilities getFacById(int id){
		return faclitiesDao.get(id);
	}

	public List<String> getInternetDevId(int modId){
		List<Object> res=deviceMapper.selectObjs(new QueryWrapper<Device>().lambda().eq(Device::getModId,modId).select(Device::getInternetDeviceId));
		return (List<String>)(List)res;
	}

	/**
	 * 根据用户所属地区统计所有临时开锁权限申请的数量
	 * @param regionId
	 * @return
	 */
	@Transactional(readOnly = true)
	public int countAllCasualApplicationByRegionId(int regionId){

		return eventlogDao.countAllCasualApplicationByRegionId(regionId);
	}
	
	/**
	 * 根据用户所属地区统计所有未处理的临时申请的数量
	 * @param regionId
	 * @return
	 */
	@Transactional(readOnly = true)
	public int countAllCasualApplicationByRegionIdNotHandle(int regionId){
		int count = eventlogDao.countAllCasualApplicationByRegionIdNotHandle(regionId);

		return count;
	}
	
	/**
	 * 查询故障数量用于显示在首页
	 * @return
	 */
	@Transactional(readOnly = true)
	public List<Faultinfo> getFaultInfo(){
		
		Pager pager = new Pager(5, 1, 5);
		
		Map<String, Object> params = new HashMap<>();
		params.put("res", "0");
		params.put("pager", pager);

		List<Faultinfo> list = faultinfoDao.getlist(params);

		return list;
	}
	
	/**
	 * 根据参数查询各模块设备数量
	 * @param params
	 * @return
	 */
	@Transactional(readOnly = true)
	public List<Devicenum> getListDevicenum(Map<String, Object> params){
		
		List<Devicenum> list = devnumDao.getlist(params);
		
		return list;
	}
	
	/**
	 * 根据参数查询最近的各模块硬件故障数据
	 * @param params
	 * @return
	 */
	@Transactional(readOnly = true)
	public List<Devbug> getListDevBug(Map<String, Object> params){
		List<Devbug> list = devBugDao.getlist(params);

		return list;
	}
	

	/**
	 * 根据地区查询当地的故障记录
	 * @param regionId
	 * @return
	 */
	@Transactional(readOnly = true)
	public List<HashMap<String, Object>> getWarningMess(int regionId){
		
		List<HashMap<String, Object>> warningMess = eventlogDao.getWarningMess(regionId);
		
		return warningMess;
	}
	
	
	/**
	 * 根据参数获取设备的某一段时间内的日志记录数据
	 * @param regionId 地区Id
	 * @param devCode 设备编码
	 * @param eventDate 日期时间
	 * @return
	 */
	@Transactional(readOnly=true)
	public List<Devlogs> getListDevlogs(int regionId,String devCode,String eventDate,Pager pager){
		
		String sql = "select * from devlogs where regionId ="+regionId+" and devCode ='"+devCode+"' and eventDate > '"+eventDate+"'";
		
		return devLogsDao.getListBySql(sql,pager);
	}

	
	/** 
	 * 根据参数统计设备一段时间内的日志记录数量
	 * @param regionId 地区Id
	 * @param devCode 设备编码
	 * @param eventDate 日期时间
	 * @return
	 */
	@Transactional(readOnly=true)
	public int countDevlogs(int regionId,String devCode,String eventDate){
		
		String sql = "select count(*) from devlogs where regionId ="+regionId+" and devCode ='"+devCode+"' and eventDate > '"+eventDate+"'";
		
		return devLogsDao.countBySql(sql);
	}
	
	/**
	 * 根据设备获取该设备的临时操作人
	 * @param devId
	 * @return
	 */
	@Transactional(readOnly=true)
	public List<Operatorview> getOperators(int devId){
		
		return operatorviewDao.getListByDevIdAndtimeScope(devId, "1", TimeUtils.getNowDateLong());
	}
	
	/**
	 * 根据设备id查找设备
	 * @author 昊琦
	 * @param id
	 * @return
	 */
	@Transactional(readOnly=true)
	public Device findDevice(int id){
		return deviceMapper.selectById(id);
	}
	
	
	/**
	 *  根据设备id和用户id查询用户申请该设备的临时开锁权限成为临时操作人的记录
	 * @param devId 设备id
	 * @param userId 用户id
	 * @return
	 */

	@Transactional(readOnly=true)
	public List<Eventlog> getOperatorApplicantRecord(int devId,int userId){
		
		Map<String, Object> param = new HashMap<>();
		
		param.put("device_id", devId);
		param.put("user_id", userId);
		param.put("type_id", 4);
		
		return eventlogDao.getlist(param);
		
	}
	
	/**
	 *  更新用户对设备的临时操作申请记录
	 * @param eventlog 临时申请记录对应的bean
	 * @param flag flag标志位：是否是最新一条记录，0：否，1：是
	 */
	@Transactional(readOnly=false)
	public void UpadateOperator(Eventlog eventlog,String flag){
		
		if (eventlog==null) {
			
		}else if (eventlog.getType_id()!=4) {
			
		}else {
			eventlog.setFlag(flag);
			eventlog.setEndTime(System.currentTimeMillis());
			eventlogDao.update(eventlog);
		}

	}
	
	/**
	 * 对某个设备添加操作人
	 * @author 周超2018年3月16日  修改
	 * 
	 * @return
	 */
	@Transactional(readOnly=false)
	public int saveOperator(Integer devID,int userId,long endTime){
		Device device = deviceMapper.selectById(devID);
		Map<String, Object> params=new HashMap<>();
		params.put(Eventlog.FieldName.device_id.toString(), devID);
		params.put(Eventlog.FieldName.user_id.toString(), userId);
		params.put(Eventlog.FieldName.type_id.toString(), 4);
		List<Eventlog> applyEventlogs = eventlogDao.getlist(params);
		//对需要重置的进行充值操作
		for(Eventlog eventlog:applyEventlogs){
			if ("1".equals(eventlog.getFlag())) {
				eventlog.setFlag("0");
				eventlog.setEndTime(System.currentTimeMillis());
				eventlogDao.update(eventlog);
			}
		}
		long startTime=System.currentTimeMillis();
		Eventlog eventlog = new Eventlog(null, device.getModId(), device.getId(), device.getFacilitiesId(), userId, 0, 4, "", "", "", "1", startTime, endTime, "", "1");
		return eventlogDao.insert(eventlog);
	}
	
	
	/**
	 *  根据前端页面传过来的checkbox等参数获取系统中设备的硬件故障列表
	 * @author 昊琦
	 * @param devD 机房锁  //4
	 * @param devL 机柜锁 //1
	 * @param devW 地井    //2
	 * @param devE 通断电 //3
	 * @param handle 是否解决的标志位 
	 * @param startTime 起始开始时间
	 * @param endTime 结束开始时间
	 * @param pager 分页的参数，不用设置pager的itemtotal属性，方法会自动填入
	 * @return
	 * @throws ParseException 
	 */
	@Transactional(readOnly=true)
	public List<Faultinfo> getFaultInfos(String devD,String devL,String devW,String devE,
			String handle,Date startTime,Date endTime,Pager pager) throws ParseException{
		//获取一周前的00点
		if (startTime==null) {
			long weekEarlier = TimeUtils.getNowDateLong()-( 7*3600*24*1000);
			//将时间转换成当天00点的date类型
			String weekEarlierStr = TimeUtils.formatTime(weekEarlier, "yyyy-MM-dd");
			weekEarlierStr+=" 00:00:00";
			
			startTime=TimeUtils.StringToDate(weekEarlierStr, "yyyy-MM-dd HH:mm:ss");
		}
		
		long f1=(startTime==null?0L:startTime.getTime());
		long t1=(endTime==null?System.currentTimeMillis():endTime.getTime());

		String sql="";
		if (!"on".equals(devD)&& !"on".equals(devL)&&!"on".equals(devE)&&!"on".equals(devW)){
			sql = " select * from faultinfo where time>='"+f1+"' and time<='"+t1+"' ";
		}
		else{
			if (!"on".equals(devD)) {
				sql += " modId!=4 ,";
			}
			if (!"on".equals(devL)) {
				sql += " modId!=1 ,";
			}
			if (!"on".equals(devW)) {
				sql += " modId!=2 ,";
			}
			if (!"on".equals(devE)) {
				sql += " modId!=3 ,";
			}
			if (sql.length()>7) {
				
				
				
				sql = sql.substring(0, sql.length() - 1);
				sql = sql.replace(",", "and");
				sql = "select * from faultinfo where time>='"+f1+"' and time<='"+t1+"' and" + sql;
			}else {
				sql = "select * from faultinfo where time>='"+f1+"' and time<='"+t1+"' ";
			}
		}

		if (handle!=null) {
			sql+=" and res='0'";
		}
	
		List<Faultinfo> list = faultinfoDao.getListBySql(sql, pager);
		
		
		if (pager!=null) {
			pager.setItemtotal(list.size());
		}
		
		//调用查询方法
		return list;
		
	}
	
	
	/**
	 * 根据地区统计该地区的设备硬件故障数量
	 * @param regionId
	 * @return
	 */
	@Transactional(readOnly=true)
	public int countFaultNum(int regionId){
		
		//设置参数
		Map<String, Object> param = new HashMap<>();
		param.put("regionId", regionId);
		
		return faultnumDao.count(param);
	}
	
	
	/**
	 * 根据name查询设备属于哪个模块
	 * @param name
	 * @return
	 */
	@Transactional(readOnly=true)
	public Module getModule(String name){
		
		Map<String, Object> params = new HashMap<>();
		params.put("name", name);
		
		List<Module> list = moduleDao.getlist(params);
		if (list==null||list.isEmpty()) {
			
			return null;
		}else{
			return list.get(0);
		}
	}
	/**
	 * 根据moduleId查询该module表中的对应记录
	 * @return
	 */
	@Transactional(readOnly=true)
	public Module getModule(int moduleId){
		
		return moduleDao.get(moduleId);
	}
	
	/**
	 * 获取某一地区在相同的地理坐标点上安装的设备个数
	 * @param regionId
	 * @return
	 */
	@Transactional(readOnly=true)
	public List<Countsamefacaddress> getSameFacAddress(int regionId){
		
		Map<String, Object> param = new HashMap<>();
		param.put("facRegionId", regionId);
		List<Countsamefacaddress> list = csfaDao.getlist(param);

		return list;
	}
	/**
	 *  该方法用来进行将临时操作人删除
	 *  
	 * @param eventID event指定值
	 */
	@Transactional(readOnly=false)
	public Integer delOperator(Integer eventID){
		Eventlog eventlog = eventlogDao.get(eventID);
		eventlog.setFlag("0");
		eventlog.setEndTime(System.currentTimeMillis());
		return eventlogDao.update(eventlog);
		
	}
	
	
	/**
	 * 确认设备是否被绑定,已被有效绑定返回该设备对象，否则返回null
	 * @param devCode
	 * @return
	 */
	@Transactional(readOnly=true)
	public Device toDecideBind(String devCode){
		
		//根据设备code查找在数据库中查找设备
		Map<String, Object> params = new HashMap<>();
		params.put("code", devCode);
		List<Device> list = deviceMapper.selectByMap(params);

		if (list==null||list.isEmpty()) {
			//如果没有查询到数据则返回null
			return null;
		}else {
			//否则获取设备信息
			Device device = list.get(0);
			//判断设备是否被绑定，且被绑定在的设施是否是有效设施
			int facId = device.getFacilitiesId();
			if (facId<=0) {
				//没被绑定返回null
				return null;
			}else{
				//如果已被绑定，则判断设施是否有效
				Facilities facilities = faclitiesDao.get(facId);
				if (facilities==null) {
					//没有此设施
					return null;
				}else{
					
					if (facilities.getWorkStu().equals("2")) {
						//该设施已停止使用
						return null;
					}else{
						return device;
					}
					
				}
			}
		}
	}
	
	/**
	 * 根据devCode查询相关deviceInfo视图中的设备的对应记录
	 * @param devCode 设备编码
	 * @return
	 */
	@Transactional(readOnly=true)
	public Deviceinfo getDeviceInfo(String devCode){
		
		Map<String, Object> params = new HashMap<>();
		
		params.put("devCode", devCode);
		
		List<Deviceinfo> list = devinfoDao.getlist(params);
		
		return list==null||list.size()==0?null:list.get(0);
	}
	
	
	/**
	 * 保存设备硬件的故障信息
	 * @param device 设备
	 * @param facilities 设施
	 * @param faultType 故障类型码
	 * @param time 时间
	 */
	@Transactional(readOnly=false)
	public void saveDevFault(Device device,Facilities facilities,int faultType,long time){
		
		Eventlog eventlog = new Eventlog(null, device.getModId(), device.getId(),facilities.getId(),facilities.getUser_id(),
				faultType, 3 , "", "", "", "0", time, 0L, "", "");
		eventlogDao.insert(eventlog);
	}
	
	
	/**
	 * 查询设备最新的历史状态
	 * @param device 设备
	 * @return
	 */
	@Transactional(readOnly=true)
	public List<Eventlog> getDevLatestStu(Device device){
		
		Map<String, Object> params = new HashMap<>();
		params.put("mod_id", device.getModId());
		params.put("device_id", device.getId());
		params.put("facilities_id", device.getFacilitiesId());
		params.put("type_id", 2);
		params.put("flag", "1");
		
		return eventlogDao.getlist(params);
	}
	
	
	/**
	 *  软清除或者软更新设备的历史记录中最新的那条历史记录(flag)
	 * @param eventlog 临时申请记录对应的bean
	 * @param flag flag标志位：是否是最新一条记录，0：否，1：是
	 */
	@Transactional(readOnly=false)
	public void upadateLatestDevStu(Eventlog eventlog,String flag){
		
		if (eventlog==null) {
			
		}else if (eventlog.getType_id()!=2) {
			
		}else {
			eventlog.setFlag(flag);
			eventlogDao.update(eventlog);
		}

	}
	
	/**
	 * 保存设备的历史状态记录
	 * @param device 设备
	 * @param userId 如果有相关的事件的发起人要存userId
	 * @param devStu 设备状态
	 * @param doorStu 门状态
	 * @param electricity 电量
	 * @param time 时间
	 * @param flag 是否是最新状态的标志位，1：最新的状态， 0：非最新的状态
	 */
	@Transactional(readOnly=false)
	public void saveDevStu(Device device,int userId,String devStu,String doorStu,String electricity,long time,String flag){
		
		//添加记录
		Eventlog eventlog = new Eventlog(null, device.getModId(), device.getId(), device.getFacilitiesId(), userId, 0, 2, devStu, doorStu, electricity, "", time, 0L, "", flag);
		
		eventlogDao.insert(eventlog);
		
	}
	
	/**
	 * 查询某地区的所有门禁或机房门的临时操作人申请记录
	 * @param regionId 地区id
	 * @param agreeChekbox 是否已经处理该条申请的checkbox状态
	 * @param condition 搜索条件
	 * @param time1  查询的时间段起始时间
	 * @param time2 查询的时间段结束时间
	 * @param pager 分页
	 * @throws ParseException 
	 */
	@Transactional(readOnly=true)
	public List<ApplyRecord> getCasualApplyRecord(int regionId, String agreeChekbox, String condition, Date time1, Date time2, Pager pager) throws ParseException{
		

		
		String sql = "select * from applyrecord where startTime>='"+time1.getTime()+"' and startTime<='"+time2.getTime()+"' and regionId ="+regionId;

		if (agreeChekbox != null&&!agreeChekbox.equals("")) {
			sql += " and res='0'";
		}
		
		if (condition!=null && !condition.equals("")) {
			sql += " and ( facArea like '%"+condition+"%' OR facDes like '%"+condition+"%' OR userName like '%"+condition+"%' )";
		}

		return applyrecordDao.getListBySql(sql, pager);
		
	}
	
	
	/**
	 * 统计查询某地区的所有门禁或机房门的临时操作人申请记录总数
	 * @param regionId 地区id
	 * @param agreeCheckbox 是否已经处理该条申请的checkbox状态
	 * @param condition 搜索条件
	 * @param time1  查询的时间段起始时间
	 * @param time2 查询的时间段结束时间
	 * @throws ParseException
	 */
	@Transactional(readOnly=true)
	public int countCasualApplyRecord(int regionId, String agreeCheckbox, String condition, Date time1, Date time2) throws ParseException{
		String sql = "select count(*) from applyrecord where startTime>='"+time1.getTime()+"' and startTime<='"+time2.getTime()+"' and regionId ="+regionId;

		if (agreeCheckbox != null && !agreeCheckbox.equals("")) {
			sql += " and res='0'";
		}
		
		if (condition!=null && !condition.equals("")) {
			sql += " and ( facArea like '%"+condition+"%' OR facDes like '%"+condition+"%' OR userName like '%"+condition+"%' )";
		}

		return applyrecordDao.countBySql(sql);
		
	}
	
	
	/**
	 * 修改工人发起的临时开锁权限的记录
	 * @param eventId 时间id
	 * @param result 0：未处理，1：同意，2：拒绝
	 */
	public void modifyCasualApplyRecord(int eventId,String result){
		
		Eventlog eventlog = eventlogDao.get(eventId);
		
		if (eventlog!=null&&eventlog.getType_id()==4) {
			
			//计算天数
			long timeNow = TimeUtils.getNowDateLong();
			//两天后
			long time2days = timeNow+(3600*24*1000*2);
			
			eventlog.setResult(result);
			eventlog.setEndTime(time2days);
			eventlogDao.update(eventlog);
		}
		

		
	}
}
